using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;

// TODO: replace these with the processor input and output types.
using TInput = System.String;
using TOutput = System.String;

namespace ContentPipelineExtension1
{
    /// <summary>
    /// This class will be instantiated by the XNA Framework Content Pipeline
    /// to apply custom processing to content data, converting an object of
    /// type TInput to TOutput. The input and output types may be the same if
    /// the processor wishes to alter data without changing its type.
    ///
    /// This should be part of a Content Pipeline Extension Library project.
    ///
    /// TODO: change the ContentProcessor attribute to specify the correct
    /// display name for this processor.
    /// </summary>
    //[ContentProcessor(DisplayName = "ContentPipelineExtension1.ContentProcessor1")]
    //public class ContentProcessor1 : ContentProcessor<TInput, TOutput>
    //{
    //    public override TOutput Process(TInput input, ContentProcessorContext context)
    //    {
    //        // TODO: process the input object, and return the modified data.
    //        throw new NotImplementedException();
    //    }
    //}

    [ContentProcessor]
    class MyTextureProcessor : ContentProcessor<TextureContent, TextureContent>
    {
        public override TextureContent Process(TextureContent input, ContentProcessorContext context)
        {
            // Convert the input to standard Color format, for ease of processing.            
            input.ConvertBitmapType(typeof(PixelBitmapContent<Color>));
            foreach (MipmapChain imageFace in input.Faces)
            {
                for (int i = 0; i < imageFace.Count; i++)
                {
                    PixelBitmapContent<Color> mip = (PixelBitmapContent<Color>)imageFace[i];
                    // Apply color keying.                    
                    mip.ReplaceColor(Color.Magenta, Color.TransparentBlack);
                    // Make sure the image is a power of two in size.      
                    int width = MakePowerOfTwo(mip.Width);
                    int height = MakePowerOfTwo(mip.Height);
                    if ((width != mip.Width) || (height != mip.Height))
                    {
                        context.Logger.LogWarning(null, input.Identity,
                            "Bitmap was not a power of two. Scaled from {0}x{1} to {2}x{3}.",
                            mip.Width, mip.Height, width, height);
                        PixelBitmapContent<Color> scaledMip;
                        scaledMip = new PixelBitmapContent<Color>(width, height);
                        BitmapContent.Copy(mip, scaledMip);
                        imageFace[i] = scaledMip;
                    }
                }
            }
            input.GenerateMipmaps(false);
            // Compress the output texture.         
            input.ConvertBitmapType(typeof(Dxt1BitmapContent));
            return input;
        }
        static int MakePowerOfTwo(int value)
        {
            int bit = 1;
            while (bit < value)
                bit *= 2;
            return bit;
        }
    }

    [ContentProcessor]
    class MyMaterialProcessor : MaterialProcessor
    {
        protected override ExternalReference<TextureContent> BuildTexture(string textureName, ExternalReference<TextureContent> texture, ContentProcessorContext context)
        {
            return context.BuildAsset<TextureContent, TextureContent>(texture, "MyTextureProcessor");
        }
    }

    [ContentProcessor]
    class MyModelProcessor : ModelProcessor
    {
        protected override MaterialContent ConvertMaterial(MaterialContent material, ContentProcessorContext context)
        {
            return context.Convert<MaterialContent, MaterialContent>(material, "MyMaterialProcessor");
        }
    }
}
